﻿/*
PainlessDAL Data Access Logic helper
Copyright (C) 2010  Eduardo de Britto Castro

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses/. 
*/
using System;
using System.Web;
using System.Runtime.Remoting.Messaging;
using System.Data;
using System.Transactions;
using System.Diagnostics;
namespace PainlessDAL
{
    /// <summary>
    /// Manages database connections and transactions
    /// </summary>
    public class DbContext : IDisposable, IEnlistmentNotification
    {
        private string _connectionStringName = null;

        public IDbConnection Connection { get; set; }
        public IDbTransaction DbTransaction { get; set; }
        public DbContext(string connectionStringName, bool autoEnlistTransaction)
        {
            this._connectionStringName = connectionStringName;
            if (this.Connection == null)
            {
                this.Connection = DbHelper.GetConnection(connectionStringName, true);
            }
            if (autoEnlistTransaction && Transaction.Current != null && this.DbTransaction == null)
            {
                Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None);
                System.Transactions.IsolationLevel tIsolation = Transaction.Current.IsolationLevel;
                System.Data.IsolationLevel dbIsolation = (System.Data.IsolationLevel)Enum.Parse(typeof(System.Data.IsolationLevel), tIsolation.ToString());
                this.DbTransaction = this.Connection.BeginTransaction(dbIsolation);
            }
        }
        ~DbContext()
        {
            Dispose();
        }
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            CloseConnection();
        }
        private void CloseConnection()
        {
            if (this.Connection != null)
            {
                this.Connection.Dispose();
                this.Connection = null;
            }
        }

        #region IEnlistmentNotification implementation
        public void Commit(Enlistment enlistment)
        {
            Debug.Print("Commit");
            this.DbTransaction.Commit();
            this.DbTransaction.Dispose();
            this.DbTransaction = null;
            CloseConnection();
            enlistment.Done();
        }

        public void InDoubt(Enlistment enlistment)
        {
            throw new NotImplementedException();
        }

        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            Debug.Print("Prepare");
            preparingEnlistment.Prepared();
        }

        public void Rollback(Enlistment enlistment)
        {
            Debug.Print("Rollback");
            this.DbTransaction.Rollback();
            this.DbTransaction.Dispose();
            this.DbTransaction = null;
            CloseConnection();
            enlistment.Done();
        }
        #endregion
    }
}